#pragma once
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QMatrix4x4>
#include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject>
#include <QSequentialAnimationGroup>
#include <QPropertyAnimation>
#include <QOpenGLExtraFunctions>
#include "core/RectangleShape.h"
#include <QMouseEvent>
#include <qstack.h>
#include "Scene.h"
#include "Camera.h"
class Render {
public:
	Render();
	~Render();
	void init();
	void initTextureProgram();
	void initProgram();
	void resize(int w, int h) {
		this->width = w;
		this->height = h;
		this->derty = true;
	}
	void render();

	Scene* getScene() {
		return this->scene;
	}
	Camera* getCamera() {
		return this->camera;
	}

	void renderShape(Shape* shape);
	void mousePressEvent(QMouseEvent* event) {
		if (event->button() == Qt::LeftButton) {
			this->oldCameraLocation->setX(this->cameraLocation->x());
			this->oldCameraLocation->setY(this->cameraLocation->y());
			this->oldCameraLocation->setZ(this->cameraLocation->z());
			this->startPointX = event->x() - this->width / 2;
			this->startPointY = this->height / 2 - event->y();
			float zz = (this->height / 2) * (this->height / 2) - this->startPointX * this->startPointX - (this->startPointY * this->startPointY);
			qDebug() << "startX:" << event->x() << "startY:" << event->y();

			if (zz > 0) {
				this->rotate = true;
			}
			else {
				return;
			}
			float currentZ = std::sqrt(zz);
			if (this->oldCameraLocation->z() < 0) {
				currentZ = -currentZ;
				startPointX = -startPointX;

			}
			this->startPoint->from(Point(startPointX, startPointY, currentZ));
			qDebug() << "startX:" << this->startPoint->x() << "startY:" << this->startPoint->y() << "startZ:" << this->startPoint->z();

		}


	};
	void mouseReleaseEvent(QMouseEvent* event) {
		this->rotate = false;

	}
	void mouseDoubleClickEvent(QMouseEvent* event) {

	}
	void mouseMoveEvent(QMouseEvent* event) {
		if (this->rotate) {
			float currentX = event->x() - this->width / 2;
			float currentY = this->height / 2 - event->y();
			float zz = (this->height / 2) * (this->height / 2) - (currentX * currentX) - (currentY * currentY);

			if (zz < 0) {
				return;
			}
			float currentZ = std::sqrt(zz);
			if (this->startPoint->z() < 0 ) {
				currentZ = -currentZ;
				currentX = -currentX;
			}

			Point endPoint = Point(currentX, currentY, currentZ);

			Point normal = Point::cross(endPoint, *startPoint);
			float angleTemp = Point::dot(*startPoint, endPoint);
			float cosAngle = angleTemp / ((this->height / 2) * (this->height / 2));
			normal.normalize();
			float angle = std::acos(cosAngle);
			QMatrix4x4 modelMatrix;
			modelMatrix.Identity();
			modelMatrix.rotate(angle * 180 / M_PI, QVector3D(normal.x(), normal.y(), normal.z()));
			QVector3D newLocation = modelMatrix * QVector3D(this->oldCameraLocation->x(), this->oldCameraLocation->y(), this->oldCameraLocation->z());
			cameraLocation->setX(newLocation.x());
			cameraLocation->setY(newLocation.y());
			cameraLocation->setZ(newLocation.z());

			camera->setToIdentity();
			camera->lookAt(*this->cameraLocation, QVector3D(0, 0, 0), QVector3D(0, 1, 0));
			this->oldCameraLocation->setX(this->cameraLocation->x());
			this->oldCameraLocation->setY(this->cameraLocation->y());
			this->oldCameraLocation->setZ(this->cameraLocation->z());
			this->startPoint->from(endPoint);

		}


	}
private:
	QOpenGLShaderProgram* program = new QOpenGLShaderProgram;
	QOpenGLShaderProgram* textureProgram = new QOpenGLShaderProgram;

	QOpenGLVertexArrayObject* vao = nullptr;
	QOpenGLVertexArrayObject* textureVao = nullptr;

	float startPointX = 0;
	float startPointY = 0;
	bool rotate = false;
	Point* startPoint = new Point(0, 0, 0);
	Camera* camera = new Camera();
	QVector3D* oldCameraLocation = new  QVector3D(0, 0, 1000);
	QVector3D* cameraLocation = new  QVector3D(0, 0, 1000);

	int mLocation = 0;
	int vLocation = 0;
	int pLocation = 0;
	int lightPosLocation = 0;
	int viewPosLocation = 0;
	int lightColorLocation = 0;
	int colorLocation = 0;
	int textureModelLocation = 0;
	int textureCameraLocation = 0;
	float width;
	float height;
	bool derty = true;
	Scene* scene = new Scene();

	QStack<QMatrix4x4>* modelStack = new QStack<QMatrix4x4>();
};